import os
import ctypes
import ctypes.util
import json
import collections
import subprocess
import fileinput
import re
import copy
import shutil

class Utils(object):
    def __init__(self):
        self.filesystems = []
        with open('/proc/filesystems') as fs:
            for line in fs:
                self.filesystems.append(line.rstrip('\n').split('\t')[1])

        self.libcloader = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)

    def mount(self, source, destination, filesystem, flags):
        if not os.access(source, os.R_OK):
            raise Exception("Could not find path " + source)
        if not os.access(destination, os.F_OK):
            os.mkdir(destination)
        if not os.access(destination, os.W_OK):
            raise Exception("Could not write to path " + destination)
        if filesystem not in self.filesystems:
            raise ValueError("Filesystem unknown")
        ret = self.libcloader.mount(ctypes.c_char_p(source),
                                    ctypes.c_char_p(destination),
                                    ctypes.c_char_p(filesystem),
                                    ctypes.c_char_p(flags),
                                    0)
        if ret != 0:
            raise RuntimeError(
                "Cannot mount {} : {}".format(source, os.strerror(ctypes.get_errno())))

    def umount(self, destination):
        ret = self.libcloader.umount(ctypes.c_char_p(destination))
        if ret != 0:
            raise RuntimeError(
                "Cannot umount {} : {}".format(destination, os.strerror(ctypes.get_errno())))
    @staticmethod
    def jsonread(filename):
        json_data = open(filename)
        data = json.load(json_data, object_pairs_hook=collections.OrderedDict)
        json_data.close()
        return data

    @staticmethod
    def runshellcommand(cmd, ignore_errors=False, debug=True):
        # use debug parameter for now, implement logging for image builder later
        if debug:
            print(cmd)
        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        output, err = p.communicate()
        rc = p.returncode
        if not ignore_errors:
            if rc != 0:
                print(err)
                raise RuntimeError("Cannot run command {}".format(cmd))
        return output.decode()

    @staticmethod
    def replaceinfile(filename, pattern, sub):
        for line in fileinput.input(filename, inplace=True):
            line = re.sub(pattern, sub, line)
            print(line)

    @staticmethod
    def replaceandsaveasnewfile(old_file, new_file, pattern, sub):
        with open(old_file, "r") as old, open(new_file, "w") as new:
            for line in old:
                line = re.sub(pattern, sub, line)
                new.write(line)

    @staticmethod
    def generatePhotonVmx(old_file, new_file, pattern, disk):
        with open(old_file, "r") as old, open(new_file, "w") as new:
            for line in old:
                if "scsi0:" in line:
                    line = re.sub(pattern, pattern + "0", line)
                    new.write(line)
                    in_text = "scsi0:0"
                    _in_text = pattern + "0"
                    for i in range(1,disk):
                        nline = copy.copy(line)
                        replace_text = "scsi0:" + str(i)
                        _replace_text = pattern + str(i)
                        nline = re.sub(in_text, replace_text, nline)
                        nline = re.sub(_in_text, _replace_text, nline)
                        new.write(nline)
                else:
                    new.write(line)

    @staticmethod
    def copyallfiles(src, target):
        files = os.listdir(src)
        for file in files:
            filename = os.path.join(src, file)
            if os.path.isfile(filename):
                shutil.copy(filename, target)
